#pragma once
#include <iostream>
#include <string>
#include <unistd.h>
#include <functional>
#include "pthread.h"
#include "LockGuard.hpp"
#include "InetAddr.hpp"
#include "Thread_pool.hpp"
#include "Log.hpp"
using task_t = std::function<void()>;
class Route
{
public:
    Route()
    {
        pthread_mutex_init(&_mutex, nullptr);
    }
    void CheckOnlineUser(InetAddr &who) //检查是否上线
    {
        LockGuard lockguard(&_mutex);
        for (auto &user : _online_user)
        {
            if (user == who) // 要在inetaddr中设置
            {
                LOG(DEBUG, "%s is exists\n", who.AddrStr().c_str());
                return;
            }
            LOG(FATAL, "%s is not exists,add it", who.AddrStr().c_str());
            _online_user.push_back(who);
        }
    }

    void Offline(InetAddr &who) //检查是否离线
    {
        LockGuard lockguard(&_mutex);
        auto iter = _online_user.end();
        for (; iter != _online_user.end(); iter++)
        {
            if (*iter == who)
            {
                LOG(DEBUG, "%s is offline\n", who.AddrStr().c_str());
                _online_user.erase(iter);
                break;
            }
        }
    }

    void ForwardHelper(int sockfd,const std::string message,InetAddr who)   //实际执行消息转发操作
    {
        LockGuard lockguard(&_mutex);
        std::string send_message="["+who.AddrStr()+"]#" + message;
        for(auto &user:_online_user)
        {
            struct sockaddr_in peer=user.Addr();
            LOG(DEBUG, "Forward message to %s, message is %s\n", user.AddrStr().c_str(), send_message.c_str());
            ::sendto(sockfd,send_message.c_str(),send_message.size(),0,(struct sockaddr*)&peer,sizeof(peer));
        }
    }

    void Forward(int sockfd,const std::string &message,InetAddr &who)   //负责检查用户在线状态、处理用户退出请求，并将消息转发任务封装成一个可调用对象添加到线程池的任务队列中
    {
        CheckOnlineUser(who);
        if(message=="quit" || message=="q")
        {
            Offline(who);
        }
        task_t t=std::bind(&Route::ForwardHelper,this,sockfd,message,who);
        //使用 std::bind 函数将 ForwardHelper 函数及其参数绑定，创建一个可调用对象 t。
        ThreadPool<task_t>::GetInstance()->Equeue(t);
        //添加任务到线程池：ThreadPool<task_t>::GetInstance()->Equeue(t); 通过单例模式获取线程池实例，并将任务 t 添加到线程池的任务队列中，实现消息转发的异步处理。
    }
    ~Route()
    {
        pthread_mutex_unlock(&_mutex);
    }
private:
    pthread_mutex_t _mutex;
    std::vector<InetAddr> _online_user;
};